package com.aicoq.example.stock.service.impl;

import com.aicoq.example.stock.persist.mapper.StockDayInfoMapper;
import com.aicoq.example.stock.persist.model.StockDayInfo;
import com.aicoq.example.stock.persist.model.StockInfo;
import com.aicoq.example.stock.persist.model.example.StockDayInfoExample;
import com.aicoq.example.stock.persist.model.example.StockInfoExample;
import com.aicoq.example.stock.service.AnalysisStockService;
import com.alibaba.fastjson2.JSON;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
public class AnalysisStockServiceImpl implements AnalysisStockService {

    @Autowired
    private StockDayInfoMapper stockDayInfoMapper;

    private final static Logger logger = LoggerFactory.getLogger(AnalysisStockServiceImpl.class);

    @Override
    public void analysisStock(int occurDate) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.execute(() -> {
            doAnalysisStock(occurDate);
        });

    }

    private void doAnalysisStock(int occurDate) {
        List<StockDayInfo> stockInfoList = queryStockInfo(occurDate);
        List<String> stockList = new ArrayList<>();
        for (StockDayInfo stock : stockInfoList) {
            boolean b = analysisStock(stock.getSymbol(), occurDate);
            if (b) {
                stockList.add(stock.getSymbol());
                logger.info("{}-{}貌似符合要求", stock.getSymbol(), stock.getName());
            }
        }

        logger.info("符合要求的列表-{}", JSON.toJSONString(stockList));
    }

    private boolean analysisStock(String symbol, int occurDate) {
        logger.info("开始分析-{}", symbol);
        List<StockDayInfo> stockInfoList = queryStockInfo(symbol, occurDate);
        if (stockInfoList.isEmpty()) {
            return false;
        }
        // 这个指标怎么算，价格的浮动特别小，但是交易金额特别大
        List<BigDecimal> changePercentList = stockInfoList.stream().map((StockDayInfo::getChangePercent)).toList();
        List<BigDecimal> turnoverRatioList = stockInfoList.stream().map(StockDayInfo::getTurnoverRatio).toList();
        boolean changePercentFlag = true;

        BigDecimal lowChange = new BigDecimal("-7");
        BigDecimal highChange = new BigDecimal("5");
        for (BigDecimal changePercent : changePercentList) {
            if (changePercentFlag && changePercent.compareTo(lowChange) < 0) {
                logger.info("开始分析-{}，最低变动幅度不符合，实际为-{}", symbol, changePercent);
                changePercentFlag = false;
            }
            if (changePercentFlag && changePercent.compareTo(highChange) > 0) {
                logger.info("开始分析-{}，最高变动幅度不符合，实际为-{}", symbol, changePercent);
                changePercentFlag = false;
            }
        }

        boolean turnoverRatioFlag = true;
        BigDecimal lowTurnover = new BigDecimal("6");
        BigDecimal highTurnover = new BigDecimal("40");
        for (BigDecimal turnoverRatio : turnoverRatioList) {
            if (turnoverRatioFlag && turnoverRatio.compareTo(lowTurnover) < 0) {
                logger.info("开始分析-{}，最低换手率不符合，实际为-{}", symbol, turnoverRatio);
                turnoverRatioFlag = false;
            }
            if (turnoverRatioFlag && turnoverRatio.compareTo(highTurnover) > 0) {
                logger.info("开始分析-{}，最高换手率不符合，实际为-{}", symbol, turnoverRatio);
                turnoverRatioFlag = false;
            }
        }

        return changePercentFlag && turnoverRatioFlag;
    }


    private List<StockDayInfo> queryStockInfo(String symbol, int occurDate) {
        int analysisDate = beforeDays(occurDate);
        StockDayInfoExample queryStockDayInfoExample = new StockDayInfoExample();
        queryStockDayInfoExample.createCriteria()
                .andSymbolEqualTo(symbol)
                .andOccurDateBetween(analysisDate, occurDate);
        queryStockDayInfoExample.setOrderByClause("occur_date");

        return stockDayInfoMapper.selectByExample(queryStockDayInfoExample);
    }

    private List<StockDayInfo> queryStockInfo(int occurDate) {
        StockDayInfoExample queryStockDayInfoExample = new StockDayInfoExample();
        queryStockDayInfoExample.createCriteria()
                .andSymbolLike("sz0%") // sh60
                .andOccurDateEqualTo(occurDate);

        return stockDayInfoMapper.selectByExample(queryStockDayInfoExample);
    }

    private int beforeDays(int occurDate) {
        try {
            Date occur = DateUtils.parseDate(occurDate + "", "yyyyMMdd");
            Date analysis = DateUtils.addDays(occur, -16);
            String analysisDate = DateFormatUtils.format(analysis, "yyyyMMdd");
            return Integer.parseInt(analysisDate);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    private int occurDate() {
        String occur = DateFormatUtils.format(new Date(), "yyyyMMdd");
        return Integer.parseInt(occur);
    }

}
